<cfcomponent displayname="UDFs" output="false" hint="Wrapper for udfs.">

	<!---
	INITIALIZATION / CONFIGURATION
	--->
	<cffunction name="init" access="public" returntype="udfs" output="false"
		hint="Initializes the udfs wrapper.">
		<cfreturn this />
 	</cffunction>


	<cffunction name="sha1" access="public" returntype="string" output="false"
		hint="Computes a SHA1 message digest.">
		<cfargument name="message" type="string" required="true" />
		<!--- Rewritten UDF from cflib.org Author: Rob Brooks-Bilson (rbils@amkor.com) --->
		<cfset var hex_msg = "" />
		<cfset var hex_msg_len = 0 />
		<cfset var padded_hex_msg = "" />
		<cfset var msg_block = "" />
		<cfset var num = 0 />
		<cfset var temp = "" />
		<cfset var h = ArrayNew(1) />
		<cfset var w = ArrayNew(1) />
		<cfset var a = "" />
		<cfset var b = "" />
		<cfset var c = "" />
		<cfset var d = "" />
		<cfset var e = "" />
		<cfset var f = "" />
		<cfset var i = 0 />
		<cfset var k = "" />
		<cfset var n = 0 />
		<cfset var t = 0 />
		
		<!--- Convert the msg to ASCII binary-coded form --->
		<cfloop from="1" to="#Len(arguments.message)#" index="i">
			<cfset hex_msg = hex_msg & Right("0" & FormatBaseN(Asc(Mid(message, i , 1)), 16), 2)>
		</cfloop>

		<!--- Compute the msg length in bits --->
		<cfset hex_msg_len = FormatBaseN(8 * Len(message), 16) />
		
		<!--- Pad the msg to make it a multiple of 512 bits long --->
		<cfset padded_hex_msg = hex_msg & "80" & RepeatString("0", 128 - ((Len(hex_msg) + 2 + 16) Mod 128)) & RepeatString("0", 16 - Len(hex_msg_len)) & hex_msg_len />

		<!--- Initialize the buffers --->
		<cfset h[1] = InputBaseN("0x67452301", 16) />
		<cfset h[2] = InputBaseN("0xefcdab89", 16) />
		<cfset h[3] = InputBaseN("0x98badcfe", 16) />
		<cfset h[4] = InputBaseN("0x10325476", 16) />
		<cfset h[5] = InputBaseN("0xc3d2e1f0", 16) />

		<!--- Process the msg 512 bits at a time --->
		<cfloop from="1" to="#Evaluate(Len(padded_hex_msg)/128)#" index="n">
			<cfset msg_block = Mid(padded_hex_msg, 128 * (n-1) + 1, 128) />
			
			<cfset a = h[1] />
			<cfset b = h[2] />
			<cfset c = h[3] />
			<cfset d = h[4] />
			<cfset e = h[5] />
			
			<cfloop from="0" to="79" index="t">
				<!--- nonlinear functions and constants --->
				<cfif t LTE 19>
					<cfset f = BitOr(BitAnd(b, c), BitAnd(BitNot(b), d)) />
					<cfset k = InputBaseN("0x5a827999", 16) />
				<cfelseif t LTE 39>
					<cfset f = BitXor(BitXor(b, c), d) />
					<cfset k = InputBaseN("0x6ed9eba1", 16) />
				<cfelseif t LTE 59>
					<cfset f = BitOr(BitOr(BitAnd(b, c), BitAnd(b, d)), BitAnd(c, d)) />
					<cfset k = InputBaseN("0x8f1bbcdc", 16) />
				<cfelse>
					<cfset f = BitXor(BitXor(b, c), d) />
					<cfset k = InputBaseN("0xca62c1d6", 16) />
				</cfif>
				
				<!--- Transform the msg block from 16 32-bit words to 80 32-bit words --->
				<cfif t LTE 15>
					<cfset w[t + 1] = InputBaseN(Mid(msg_block, 8 * t + 1, 8), 16) />
				<cfelse>
					<cfset num = BitXor(BitXor(BitXor(w[t - 3 + 1], w[t - 8 + 1]), w[t -14 + 1]), w[t - 16 + 1]) />
					<cfset w[t + 1] = BitOr(BitSHLN(num, 1), BitSHRN(num, 32 - 1)) />
				</cfif>
				
				<cfset temp = BitOr(BitSHLN(a, 5), BitSHRN(a, 32 - 5)) + f + e + w[t + 1] + k />
				<cfset e = d />
				<cfset d = c />
				<cfset c = BitOr(BitSHLN(b, 30), BitSHRN(b, 32 - 30)) />
				<cfset b = a />
				<cfset a = temp />
				<cfset num = a />
				
				<cfloop condition="(num LT -2^31) OR (num GE 2^31)">
					<cfset num = num - Sgn(num) * 2 ^ 32 />
				</cfloop>
				
				<cfset a = num />
			</cfloop>
			
			<cfset h[1] = h[1] + a />
			<cfset h[2] = h[2] + b />
			<cfset h[3] = h[3] + c />
			<cfset h[4] = h[4] + d />
			<cfset h[5] = h[5] + e />
			
			<cfloop from="1" to="5" index="i">
				<cfloop condition="(h[i] LT -2 ^ 31) OR (h[i] GTE 2 ^ 31)">
					<cfset h[i] = h[i] - Sgn(h[i])* 2 ^ 32 />
				</cfloop>
			</cfloop>
		</cfloop>
		
		<cfloop from="1" to="5" index="i">
			<cfset h[i] = RepeatString("0", 8 - Len(FormatBaseN(h[i], 16))) & UCase(FormatBaseN(h[i], 16)) />
		</cfloop>
		
		<cfreturn h[1] & h[2] & h[3] & h[4] & h[5] />
	</cffunction>
</cfcomponent>